using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
// using ADODB;

namespace Webber
{
    static class IOHelper
    {
        private static FPSEPublish.FPSEPublish m_SPPublish;

        private static System.Collections.ArrayList m_invalidFileChar;
        private static System.Collections.ArrayList m_invalidPathChar;

        static IOHelper()
        {
            m_SPPublish = new FPSEPublish.FPSEPublish();

            m_invalidFileChar = new System.Collections.ArrayList();
            m_invalidPathChar = new System.Collections.ArrayList();

            foreach (char c in System.IO.Path.GetInvalidFileNameChars())
            {
                m_invalidFileChar.Add(c);
            }

            foreach (char c in System.IO.Path.GetInvalidPathChars())
            {
                m_invalidPathChar.Add(c);
            }
        }

        public static bool WriteFile(string strFileName, string strFileContents, bool append, out string error)
        {
            bool result = true;
            error = null;

            try
            {
                System.IO.StreamWriter file = new System.IO.StreamWriter(strFileName, append);
                file.Write(strFileContents);
                file.Close();
            }
            catch (Exception e)
            {
                error = e.Message;
                result = false;
            }

            return result;
        }
        

        // we will overwrite if targetDir is already there
        public static bool CopyDirectory(string srcDir, string targetDir, out string error, IExportMonitor status)
        {
            bool result = true;
            error = null;

            // check if source directory exists
            if (!System.IO.Directory.Exists(srcDir))
            {
                result = false;
                error = "Invalid source directory: " + srcDir;
            }
            else
            {
                // blow away target directory
                DeleteDirectory(targetDir, out error);

                // create target directory
                try
                {
                    System.IO.Directory.CreateDirectory(targetDir);
                }
                catch (Exception e)
                {
                    error = e.Message;
                    result = false;
                }

                // copy contents if we made it this far
                if (result == true)
                {
                    bool bTerminate = false;
                    if (status != null) bTerminate = status.ShouldStop();

                    // Get files
                    string[] files = System.IO.Directory.GetFileSystemEntries(srcDir);

                    // copy files
                    string strFileNameAbs;
                    string strFileName;
                    string strTarget;

                    for (int i = 0; i < files.Length && result && !bTerminate; i++)
                    {
                        strFileNameAbs = files[i];
                        strFileName = System.IO.Path.GetFileName(strFileNameAbs);
                        strTarget = targetDir + "\\" + strFileName;

                        if (System.IO.Directory.Exists(strFileNameAbs))
                        {
                            result = CopyDirectory(strFileNameAbs, strTarget, out error, status);
                        }
                        else
                        {
                            if (status != null) status.CurrentStatus("Copying " + strFileName + " to " + targetDir);
                            result = IOHelper.CopyFile(strFileNameAbs, strTarget, out error);
                            if (status != null) status.Increment(1);
                            if (status != null) status.CurrentStatus("");
                        }

                        if (status != null) bTerminate = status.ShouldStop();
                    }

                    if (bTerminate)
                    {
                        result = false;
                        error = "Operation manually aborted.";
                    }
                }
            }
            return result;
        }

        private static bool CopyDirectoryWebDAVHelper(string srcDir, string targetDir, out string error, IExportMonitor status)
        {
            bool result = true;
            error = null;

            // targetDir = HttpUtility.UrlPathEncode(targetDir);

            // check if source directory exists
            if (!System.IO.Directory.Exists(srcDir))
            {
                result = false;
                error = "Invalid source directory: " + srcDir;
            }

            // Ensure there is a "/" at end of targetDir
            if (targetDir[targetDir.Length - 1] != '/')
            {
                targetDir += '/';
            }

            // blow away / create target directory
            if (result) result = IOHelper.DeleteFileOrFolderWebDAV(targetDir, out error);
            if (result) result = IOHelper.CreateDirectoryWebDAV(targetDir, out error);

            // copy files if we made it this far
            if (result)
            {
                bool bTerminate = false;
                if (status != null) bTerminate = status.ShouldStop();

                // Get files
                string[] files = System.IO.Directory.GetFileSystemEntries(srcDir);

                // copy files
                string strFileNameAbs;
                string strFileName;
                string strTarget;

                for (int i = 0; i < files.Length && result && !bTerminate; i++)
                {
                    strFileNameAbs = files[i];
                    strFileName = System.IO.Path.GetFileName(strFileNameAbs);
                    strTarget = targetDir + strFileName;

                    // if this a directory?
                    if (System.IO.Directory.Exists(strFileNameAbs))
                    {
                        // copy the directory instead
                        result = IOHelper.CopyDirectoryWebDAVHelper(strFileNameAbs, strTarget, out error, status);
                    }
                    else
                    {
                        if (status != null) status.CurrentStatus("Copying " + strFileName + " to " + targetDir);
                        result = IOHelper.CopyFileWebDAVHelper(strFileNameAbs, strTarget, out error);
                        if (status != null) status.Increment(1);
                        if (status != null) status.CurrentStatus("");
                    }

                    // check is we should stop
                    if (status != null) bTerminate = status.ShouldStop();
                }

                // update status flag
                if (bTerminate)
                {
                    result = false;
                    error = "Operation manually aborted.";
                }
            }
            return result;
        }

        // will overwrite targetDir if it is already there
        public static bool CopyDirectoryWebDAV(string srcDir, string targetDir, out string error, IExportMonitor status)
        {
            // set the target location
            m_SPPublish.CacheSPSiteUrl(targetDir);

            bool result = CopyDirectoryWebDAVHelper(srcDir, targetDir, out error, status);

            // invalidate cache
            m_SPPublish.InvalidateCache();

            return result;

        }

        // Description: Creates an empty directory
        // Args: strOutPath - absolute path of directory to be created
        public static bool DeleteDirectory(string path, out string error)
        {
            bool result = true;
            error = null;

            if (System.IO.Directory.Exists(path))
            {
                try
                {
                    System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(path);
                    directory.Delete(true);
                }
                catch (Exception e)
                {
                    error = e.Message;
                    result = false;
                }
            }
            return result;
        }

        public static bool DeleteFileOrFolderWebDAV(string targetDir, out string error)
        {
            bool result = true;
            error = "";
            try
            {
                // Delete a folder
                m_SPPublish.RemoveFileOrFolder(targetDir);
            }
            catch (Exception e)
            {
                result = false;
                error = e.Message;
            }

            return result;
        }


        public static bool CreateDirectory(string path, out string error)
        {
            bool result = true;
            error = null;

            try
            {
                // create the directory again
                System.IO.Directory.CreateDirectory(path);
            }
            catch (Exception e)
            {
                error = e.Message;
                result = false;
            }

            return result;
        }

        public static bool CreateDirectoryWebDAV(string targetDir, out string error)
        {
            bool result = true;
            error = "";

            // make sure there is no '/' at the end
            if (targetDir[targetDir.Length - 1] == '/')
            {
                targetDir = targetDir.Substring(0, targetDir.Length - 1);
            }

            try
            {
                // Create a folder
                m_SPPublish.CreateFolder(targetDir);
            }
            catch (Exception e)
            {
                result = false;
                error = e.Message;
            }
            return result;
        }

        
        public static bool CopyFile(string srcFile, string tgtFile, out string error)
        {
            bool result = true;
            error = "";

            try
            {
                System.IO.File.Copy(srcFile, tgtFile, true);
            }
            catch (Exception e)
            {
                result = false;
                error = e.Message;
            }

            return result;
        }

        private static bool CopyFileWebDAVHelper(string srcFile, string desFile, out string error)
        {
            bool result = true;
            error = "";

            desFile = HttpUtility.UrlPathEncode(desFile);

            try
            {
                m_SPPublish.PutDocument(desFile, srcFile, "");
            }
            catch (Exception e)
            {
                result = false;
                error = e.Message;
            }

            return result;
        }

        public static bool CopyFileWebDAV(string srcFile, string desFile, out string error)
        {
            // set the server location

            return CopyFileWebDAVHelper(srcFile, desFile, out error);
        }
  
        public static string GetCleanFileName(string filename)
        {
            string cleanFileName = "";

            foreach (char c in filename)
            {
                if (!m_invalidFileChar.Contains(c)) cleanFileName += c;
            }
            return cleanFileName;
        }

        public static string GetCleanPathName(string pathname)
        {
            string cleanPathName = "";

            foreach (char c in pathname)
            {
                if (!m_invalidPathChar.Contains(c)) cleanPathName += c;
            }
            return cleanPathName;
        }

        public static string MakeTempDirectory()
        {
            const int MAX_DIR = 20;

            // this is the default temp location
            string location = System.IO.Path.GetTempPath() + "OneNote Webber\\";
            string error = null;

            // find a subdirectory that doesn't exist yet
            int idx = 1;
            while (System.IO.Directory.Exists(location + idx.ToString()) && idx < MAX_DIR)
            {
                idx ++;
            }

            // clean up directories if we exceeded max
            string err;
            if (idx == MAX_DIR)
            {
                for (int i = 0; i < MAX_DIR; i++)
                {
                    if (!DeleteDirectory(location + i.ToString(), out err))
                    {
                        // no error currently reported if we fail to purge temp directory
                    }
                }
            }

            // we found a potential subdirectory within out 100 folder limit
            if (idx < 100)
            {
                // try to create directory
                location += idx.ToString() + "\\";             
                if (!CreateDirectory(location,out error))
                {
                    location = "";
                }
            }
            else
            {
                location = "";
            }
            return location;
        }
    }
}
